package com.habdqn.studentmanager.util;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.habdqn.studentmanager.constant.Constant;
import com.habdqn.studentmanager.exception.StudentException;

/**
 * @author Administrator
 * 
 *         2017年5月31日
 * 
 */
public class AESUtil {

	private static final Logger logger = LoggerFactory.getLogger(AESUtil.class);

	/**
	 * 在配置文件中的key值
	 */
	private static final String configKey = "password";
	/**
	 * 加密密钥
	 */
	private static byte[] password;

	static {
		try {
			password = ConfigUtil.getKey(configKey).getBytes(Constant.UTF8);
		}
		catch (Exception e) {
			logger.error("AES初始化失败", e);
			throw new StudentException("AES初始化失败", e);
		}
	}

	private static byte[] encrypt(byte[] plainBytes, byte[] password)
	        throws InvalidKeyException, UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException,
	        IllegalBlockSizeException, BadPaddingException {
		Cipher cipher = init(Cipher.ENCRYPT_MODE);
		return cipher.doFinal(plainBytes);
	}

	private static byte[] decrypt(byte[] cipherBytes, byte[] password)
	        throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, UnsupportedEncodingException,
	        NoSuchAlgorithmException, NoSuchPaddingException {
		Cipher cipher = init(Cipher.DECRYPT_MODE);
		return cipher.doFinal(cipherBytes);
	}

	/**
	 * 加密一段字符串
	 * @param plainText
	 * @return
	 */
	public static String encrypt(String plainText) {
		try {
			byte[] plainBytes = plainText.getBytes(Constant.UTF8);
			byte[] cipherBytes = encrypt(plainBytes, password);
			cipherBytes = Base64.getEncoder().encode(cipherBytes);
			return new String(cipherBytes, Constant.UTF8);
		}
		catch (GeneralSecurityException e) {
			logger.error("加密失败", e);
			throw new StudentException("加密失败", e);
		}
		catch (UnsupportedEncodingException e) {
			logger.error("不支持的字符编码:{}", Constant.UTF8, e);
			throw new StudentException("不支持的字符编码", e);
		}
	}

	/**
	 * 解密一段字符串
	 * @param cipherText
	 * @return
	 */
	public static String decrypt(String cipherText) {
		try {
			byte[] cipherBytes = Base64.getDecoder().decode(cipherText.getBytes(Constant.UTF8));
			byte[] plainBytes = decrypt(cipherBytes, password);
			return new String(plainBytes, Constant.UTF8);
		}
		catch (GeneralSecurityException e) {
			logger.error("解密失败", e);
			throw new StudentException("解密失败", e);
		}
		catch (UnsupportedEncodingException e) {
			logger.error("不支持的字符编码:{}", Constant.UTF8, e);
			throw new StudentException("不支持的字符编码", e);
		}
	}

	/**
	 * 初始化 Cipher
	 * 
	 * @param opmode
	 *            模式
	 * @return
	 * @see Cipher#ENCRYPT_MODE
	 * @throws UnsupportedEncodingException
	 * @throws NoSuchPaddingException
	 * @throws NoSuchAlgorithmException
	 * @throws InvalidKeyException
	 */
	private static Cipher init(int opmode)
	        throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
		
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		random.setSeed(password);
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		kgen.init(128, random);
		SecretKey secretKey = kgen.generateKey();
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		cipher.init(opmode, key);
		return cipher;
	}
}
